package org.jsola.hr.web;

import org.jsola.admin.constant.AdminPermissionConstants;
import org.jsola.admin.constant.AminRightOprTypeEnum;
import org.jsola.admin.service.IAddedServiceOpenService;
import org.jsola.admin.service.IMenuService;
import org.jsola.admin.vo.AddedServiceListVO;
import org.jsola.admin.vo.AllPermissionVO;
import org.jsola.admin.vo.MenuVO;
import org.jsola.common.ArrayKit;
import org.jsola.common.TreeKit;
import org.jsola.core.Result;
import org.jsola.exception.ParamException;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dto.permission.RoleMemberAddDTO;
import org.jsola.hr.dto.permission.RoleMemberUpdateDTO;
import org.jsola.hr.dto.permission.UpdateRoleDTO;
import org.jsola.hr.provider.IAdminProviderService;
import org.jsola.hr.provider.IPermissionProviderService;
import org.jsola.hr.provider.IUserProviderService;
import org.jsola.hr.query.permission.RoleMemberQuery;
import org.jsola.hr.service.IHrPermissionService;
import org.jsola.hr.vo.permission.RoleMemberVO;
import org.jsola.permission.common.PermissionKit;
import org.jsola.permission.constant.PermissionConstants;
import org.jsola.permission.dao.IRightDAO;
import org.jsola.permission.dto.RoleAddDTO;
import org.jsola.permission.dto.RoleRightAddDTO;
import org.jsola.permission.dto.RoleUpdateDTO;
import org.jsola.permission.entity.PermissionDO;
import org.jsola.permission.entity.RightDO;
import org.jsola.permission.entity.RoleDO;
import org.jsola.permission.exception.PermissionException;
import org.jsola.permission.query.RoleQuery;
import org.jsola.permission.service.IPermissionService;
import org.jsola.permission.service.IRightService;
import org.jsola.permission.vo.RoleListVO;
import org.jsola.permission.vo.RoleRightListVO;
import org.jsola.permission.vo.RoleVO;
import org.jsola.user.core.TokenUser;
import org.jsola.user.core.UserContext;
import org.jsola.user.entity.UserDO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import tk.mybatis.mapper.entity.Example;

import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

import static org.jsola.hr.constant.HrPermissionConstants.*;

/**
 * @author JanusMix
 */
@RestController("hrPermissionController")
@RequestMapping(HrConstants.API_PATH + "/v1/permissions")
public class PermissionController implements IPermissionControllerAPI {

    @Autowired
    private IPermissionProviderService permissionProviderService;
    @Autowired
    private org.jsola.admin.provider.IPermissionProviderService adminPermissionProviderService;
    @Autowired
    private IUserProviderService userProviderService;
    @Autowired
    private IAdminProviderService adminProviderService;
    @Autowired
    private IHrPermissionService hrPermissionService;

    @Override
    @GetMapping
    public Result<AllPermissionVO> listUserPermission(@RequestParam(required = false) String companyId) {
        TokenUser tokenUser = UserContext.getUser();

        AllPermissionVO allPermissionVO = hrPermissionService.listUserPermission(companyId, tokenUser);
        return Result.success(allPermissionVO);
    }

    @Override
    @GetMapping("listUserPermission2")
    @Deprecated
    public Result<AllPermissionVO> listUserPermission2(@RequestParam(required = false) String companyId) {
        TokenUser tokenUser = UserContext.getUser();
        AllPermissionVO allPermissionVO = adminProviderService.getAllPermission2(tokenUser.getUserId(), companyId, COMPANY_SUBJECT_TYPE, tokenUser.getSiteId());
        //管理员加载所有菜单和原子权限串
        if (hrPermissionService.isAdmin(tokenUser.getUserId(), tokenUser.getSiteId())) {
            List<String> subjectTypeList = new ArrayList<>();
            subjectTypeList.add(SYSTEM_SUBJECT_TYPE);
            subjectTypeList.add(HR_SUBJECT_TYPE);
            subjectTypeList.add(COMPANY_SUBJECT_TYPE);
            allPermissionVO.setMenuList(adminProviderService.getMenuList(subjectTypeList));
            List<String> pmsStringList = allPermissionVO.getPermissionStringList();
            if (!CollectionUtils.isEmpty(pmsStringList)) {
                pmsStringList.addAll(permissionProviderService.getPermissionStringList(permissionProviderService.getPermissionList(COMPANY_SUBJECT_TYPE)));
            }
        }
        return Result.success(allPermissionVO);
    }

    @Override
    @GetMapping("listUserPermissionForApp")
    public Result<AllPermissionVO> listUserPermissionForApp(@RequestParam(required = false) String companyId) {
        TokenUser tokenUser = UserContext.getUser();

        AllPermissionVO allPermissionVO = hrPermissionService.listUserPermissionForApp(companyId, tokenUser);
        return Result.success(allPermissionVO);
    }

    @GetMapping("/roleList")
    @Override
    public Result<List<RoleListVO>> queryRoleList(@Validated RoleQuery roleQuery) {
        TokenUser tokenUser = UserContext.getUser();
        if (!COMPANY_SUBJECT_TYPE.equals(roleQuery.getSubjectType()) &&
                !HR_SUBJECT_TYPE.equals(roleQuery.getSubjectType())) {
            throw new ParamException(PERMISSION_DENIED_MESSAGE);
        }
        return Result.success(permissionProviderService.queryRoleList(roleQuery, tokenUser.getSiteId()));
    }

    @PostMapping("/addRole")
    @Override
    public Result<String> addRole(@RequestBody @Validated RoleAddDTO roleAddDTO) {
        TokenUser tokenUser = UserContext.getUser();
        if (!COMPANY_SUBJECT_TYPE.equals(roleAddDTO.getSubjectType()) &&
                !HR_SUBJECT_TYPE.equals(roleAddDTO.getSubjectType())) {
            throw new ParamException(PERMISSION_DENIED_MESSAGE);
        }
        PermissionException.isTrue(hrPermissionService.hasRight(tokenUser.getUserId(), tokenUser.getSiteId(), HR_ENTERPRISESETUP_ROLEMANAGEMENT), PERMISSION_DENIED_MESSAGE);
        roleAddDTO.setSubjectId(PermissionConstants.DEFAULT_SUBJECT_ID);
        //新增角色
        permissionProviderService.addRole(roleAddDTO, tokenUser);

        return Result.success();
    }

    @PostMapping("/updateRole")
    @Override
    public Result<String> updateRole(@RequestBody @Validated UpdateRoleDTO updateRoleDTO) {
        TokenUser tokenUser = UserContext.getUser();
        PermissionException.isTrue(hrPermissionService.hasRight(tokenUser.getUserId(), tokenUser.getSiteId(), HR_ENTERPRISESETUP_ROLEMANAGEMENT), PERMISSION_DENIED_MESSAGE);
        RoleDO roleDO = permissionProviderService.findRoleById(updateRoleDTO.getRoleId(), tokenUser.getSiteId());
        ParamException.notNull(roleDO, "角色不存在");
        RoleUpdateDTO roleUpdateDTO = new RoleUpdateDTO();
        roleUpdateDTO.setId(updateRoleDTO.getRoleId());
        roleUpdateDTO.setName(updateRoleDTO.getName());
        roleUpdateDTO.setType(updateRoleDTO.getType());
        roleUpdateDTO.setDescription(updateRoleDTO.getDescription());
        permissionProviderService.updateRole(roleUpdateDTO, tokenUser);

        return Result.success();
    }

    @PostMapping("/deleteRoles")
    @Override
    public Result<String> deleteRoles(Long[] roleIds) {
        TokenUser tokenUser = UserContext.getUser();
        ParamException.notNull(roleIds, "请选择角色");
        PermissionException.isTrue(hrPermissionService.hasRight(tokenUser.getUserId(), tokenUser.getSiteId(), HR_ENTERPRISESETUP_ROLEMANAGEMENT), PERMISSION_DENIED_MESSAGE);
        Arrays.stream(roleIds).forEach(roleId -> permissionProviderService.deleteRoleById(roleId, tokenUser));
        return Result.success();
    }

    @Override
    @GetMapping(value = "/roles/{roleId}")
    public Result<RoleVO> findById(@PathVariable Long roleId) {
        TokenUser tokenUser = UserContext.getUser();
        PermissionException.isTrue(hrPermissionService.hasRight(tokenUser.getUserId(), tokenUser.getSiteId(), HR_ENTERPRISESETUP_ROLEMANAGEMENT), PERMISSION_DENIED_MESSAGE);
        RoleDO roleDO = permissionProviderService.findRoleById(roleId, tokenUser.getSiteId());
        RoleVO roleVO = roleDO.to(RoleVO.class);
        Map<String, Long> countMap = permissionProviderService.getRoleRightCountMap(roleDO.getSubjectType(), tokenUser.getSiteId());
        roleVO.setPermissionCount(countMap.get(roleDO.getId() + "") == null ? 0L : countMap.get(roleDO.getId() + ""));
        return Result.success(roleVO);
    }

    @GetMapping("/rightList")
    @Override
    public Result<List<RoleRightListVO>> queryRightList(String subjectType, Long roleId) {
        TokenUser tokenUser = UserContext.getUser();
//        if (!COMPANY_SUBJECT_TYPE.equals(subjectType) &&
//                !HR_SUBJECT_TYPE.equals(subjectType)) {
//            throw new ParamException(PERMISSION_DENIED_MESSAGE);
//        }
//        PermissionException.isTrue(hrPermissionService.hasRight(tokenUser.getUserId(), tokenUser.getSiteId(), HR_ENTERPRISESETUP_ROLEMANAGEMENT), PERMISSION_DENIED_MESSAGE);
        //站点拥有的subjectType集合
        List<String> subjectTypeList = adminProviderService.selectSubjectTypesBySiteAndType(subjectType, tokenUser.getSiteId());
        List<RoleRightListVO> resultList = new ArrayList<>();
        subjectTypeList.forEach(p ->
                resultList.addAll(permissionProviderService.queryRightList(p, tokenUser.getSiteId(), roleId))
        );
        return Result.success(resultList);
    }

    @PostMapping("/saveRoleRight")
    @Override
    public Result<String> saveRoleRight(@RequestBody @Validated List<RoleRightAddDTO> roleRightDTOs) {
        TokenUser tokenUser = UserContext.getUser();
        ParamException.notNull(roleRightDTOs, "角色授权列表不能为空");
        PermissionException.isTrue(hrPermissionService.hasRight(tokenUser.getUserId(), tokenUser.getSiteId(), HR_ENTERPRISESETUP_ROLEMANAGEMENT), PERMISSION_DENIED_MESSAGE);
        roleRightDTOs.forEach(roleRightDTO -> {
//            if (!COMPANY_SUBJECT_TYPE.equals(roleRightDTO.getSubjectType()) &&
//                    !HR_SUBJECT_TYPE.equals(roleRightDTO.getSubjectType())) {
//                throw new ParamException(PERMISSION_DENIED_MESSAGE);
//            }
            permissionProviderService.saveRoleRight(tokenUser.getUserId(),
                    roleRightDTO.getRoleId(),
                    roleRightDTO.getSubjectType(),
                    PermissionConstants.DEFAULT_SUBJECT_ID.split(","),
                    ArrayKit.splitToLongs(roleRightDTO.getPermissionIds(), ","),
                    tokenUser.getSiteId());
        });
        return Result.success();
    }

    @GetMapping("/roleMemberList")
    @Override
    public Result<List<RoleMemberVO>> queryRoleMembers(@Validated RoleMemberQuery roleMemberQuery) {
        TokenUser tokenUser = UserContext.getUser();
//        PermissionException.isTrue(hrPermissionService.hasRight(tokenUser.getUserId(), tokenUser.getSiteId(), COMPANY_COMPANYMANAGE_MEMBER), PERMISSION_DENIED_MESSAGE);
        return Result.success(permissionProviderService.queryRoleMemberList(roleMemberQuery, tokenUser));
    }

    @PostMapping("/addRoleMember")
    @Override
    public Result<String> addRoleMember(@RequestBody @Valid RoleMemberAddDTO roleMemberAddDTO) {
        TokenUser tokenUser = UserContext.getUser();
//        PermissionException.isTrue(hrPermissionService.hasRight(tokenUser.getUserId(), tokenUser.getSiteId(), COMPANY_COMPANYMANAGE_MEMBER), PERMISSION_DENIED_MESSAGE);
        //查询角色
        RoleDO roleDO = permissionProviderService.findRoleById(roleMemberAddDTO.getRoleId(), tokenUser.getSiteId());
        ParamException.notNull(roleDO, "角色不存在");

        String[] memberIds = roleMemberAddDTO.getMemberIds();
        List<org.jsola.permission.dto.RoleMemberAddDTO> roleMemberList = new ArrayList<>();
        Arrays.stream(memberIds).forEach(id -> {
            //用户已经拥有的角色
            List<Long> roleIdList = permissionProviderService.findRoleIdListByUserId(id, COMPANY_SUBJECT_TYPE,
                    roleMemberAddDTO.getCompanyId(), tokenUser.getSiteId());
            //人力系统一个用户只能有一个角色
            if (CollectionUtils.isEmpty(roleIdList)) {
                org.jsola.permission.dto.RoleMemberAddDTO roleMemberDO = new org.jsola.permission.dto.RoleMemberAddDTO();
                roleMemberDO.setRoleId(roleDO.getId());
                roleMemberDO.setMemberId(id);
                roleMemberDO.setType(PermissionConstants.ROLE_MEMBER_TYPE_USER);
                roleMemberDO.setSubjectType(COMPANY_SUBJECT_TYPE);
                roleMemberDO.setSubjectId(roleMemberAddDTO.getCompanyId());
                roleMemberList.add(roleMemberDO);
            } else {
                UserDO userDO = userProviderService.selectUserById(id);
                throw new ParamException("手机号" + userDO.getPhone() + "的账户已存在角色，添加失败");
            }
        });
        //添加角色成员
        permissionProviderService.addRoleMemberBatch(roleMemberList, tokenUser);

        return Result.success();
    }

    @PostMapping("/deleteRoleMember")
    @Override
    public Result<String> deleteRoleMember(String companyId, String memberId) {
        TokenUser tokenUser = UserContext.getUser();
//        PermissionException.isTrue(hrPermissionService.hasRight(tokenUser.getUserId(), tokenUser.getSiteId(), COMPANY_COMPANYMANAGE_MEMBER), PERMISSION_DENIED_MESSAGE);
        ParamException.notNull(memberId, "用户id不能为空");
        ParamException.notNull(companyId, "公司id不能为空");

        String[] memberIds = memberId.split(",");
        Arrays.stream(memberIds).forEach(id -> {
            //用户已经拥有的角色
            List<Long> roleIdList = permissionProviderService.findRoleIdListByUserId(id, COMPANY_SUBJECT_TYPE,
                    companyId, tokenUser.getSiteId());
            //全部删除
            roleIdList.forEach(roleId -> {
                //删除角色成员
                permissionProviderService.deleteRoleMember(id, roleId, COMPANY_SUBJECT_TYPE, companyId, tokenUser.getSiteId());
            });
        });

        return Result.success();
    }

    @PostMapping("/updateRoleMember")
    @Override
    public Result<String> updateRoleMember(@RequestBody @Valid RoleMemberUpdateDTO roleMemberUpdateDTO) {
        TokenUser tokenUser = UserContext.getUser();
//        PermissionException.isTrue(hrPermissionService.hasRight(tokenUser.getUserId(), tokenUser.getSiteId(), COMPANY_COMPANYMANAGE_MEMBER), PERMISSION_DENIED_MESSAGE);
        //查询角色
        RoleDO roleDO = permissionProviderService.findRoleById(roleMemberUpdateDTO.getRoleId(), tokenUser.getSiteId());
        ParamException.notNull(roleDO, "角色不存在");

        //用户已经拥有的角色
        List<Long> roleIdList = permissionProviderService.findRoleIdListByUserId(roleMemberUpdateDTO.getMemberId(), COMPANY_SUBJECT_TYPE,
                roleMemberUpdateDTO.getCompanyId(), tokenUser.getSiteId());
        //删除之前角色成员
        permissionProviderService.deleteRoleMember(roleMemberUpdateDTO.getMemberId(), roleIdList.get(0),
                COMPANY_SUBJECT_TYPE, roleMemberUpdateDTO.getCompanyId(), tokenUser.getSiteId());

        org.jsola.permission.dto.RoleMemberAddDTO roleMemberDO = new org.jsola.permission.dto.RoleMemberAddDTO();
        roleMemberDO.setRoleId(roleDO.getId());
        roleMemberDO.setMemberId(roleMemberUpdateDTO.getMemberId());
        roleMemberDO.setType(PermissionConstants.ROLE_MEMBER_TYPE_USER);
        roleMemberDO.setSubjectType(COMPANY_SUBJECT_TYPE);
        roleMemberDO.setSubjectId(roleMemberUpdateDTO.getCompanyId());
        //添加角色成员
        permissionProviderService.addRoleMemberBatch(Collections.singletonList(roleMemberDO), tokenUser);

        return Result.success();
    }

}
